package hamsterpolice.todo.model;

import hamsterpolice.todo.data.CategoryTable;
import hamsterpolice.todo.data.Criteria;
import hamsterpolice.todo.data.DataAdapter;
import hamsterpolice.todo.data.DataNotFoundException;
import hamsterpolice.todo.data.ToDoListOpenHelper;
import hamsterpolice.todo.data.UnhandledCriteriaException;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

class CategoryDataAdapter implements DataAdapter<Category> {

	private static final String TAG = "CategoryDataAdapter";
	private Context context = null;
	private SQLiteDatabase database = null;
	private String[] allColumns = new String[] { CategoryTable.COLUMN_ID,
			CategoryTable.COLUMN_NAME,
			CategoryTable.COLUMN_USER_ID };

	public CategoryDataAdapter(Context context) {
		this.context = context;
		database = ToDoListOpenHelper.getInstance(context)
				.getWritableDatabase();
	}

	@Override
	public Cursor get(Criteria<?> criteria) throws UnhandledCriteriaException {

		if(criteria instanceof UserCriterion){
			return getByUser(((UserCriterion) criteria).getValue());
		}
		else if (criteria instanceof IDCriterion) {
			long id = ((IDCriterion) criteria).getValue().longValue();
			return getByID(id);
		}

		throw new UnhandledCriteriaException();
	}
	
	private Cursor getByUser(User user){
		Log.v(TAG, String.format("Getting all Categories for %s", user.getUsername()));
		
		Cursor cursor = null;
		
		cursor = database.query(CategoryTable.TABLE_NAME, allColumns,
				CategoryTable.COLUMN_USER_ID + " = " + user.getID(), null, null, null,
				CategoryTable.COLUMN_NAME + " asc");

		return cursor;
	}
	
	private Cursor getByID(long id){
		Log.v(TAG, String.format("Getting category for id=%s", id));

		Cursor cursor = null;

		cursor = database.query(CategoryTable.TABLE_NAME, allColumns,
				CategoryTable.COLUMN_ID + " = " + id, null, null, null,
				null);

		return cursor;
	}

	@Override
	public long load(Cursor c, Category model) {
		if (c == null || c.isClosed())
			throw new IllegalArgumentException("Cursor is null or closed.");
		if (c.isBeforeFirst() || c.isAfterLast())
			throw new RuntimeException(
					"There is no record at the cursor's current location");
		
		long id = c.getLong(c.getColumnIndex(CategoryTable.COLUMN_ID));

		model.setName(c.getString(c.getColumnIndex(CategoryTable.COLUMN_NAME)));
		
		// Set User
		try {
			model.setUser(User.get(context, c.getLong(c.getColumnIndex(CategoryTable.COLUMN_USER_ID))));
		} catch (DataNotFoundException e) {
			throw new RuntimeException(String.format("Invalid user id on Category %s (%s)", model.getName(), id), e);
		}
		
		return c.getLong(c.getColumnIndex(CategoryTable.COLUMN_ID));
	}

	@Override
	public long insert(Category model) {
		if (!model.isNew())
			throw new IllegalArgumentException(
					"Cannot insert a model that is not new");
		Log.v(TAG, String.format("Inserting Category %s", model.getName()));
		ContentValues content = getContentValues(model);
		return database.insertOrThrow(CategoryTable.TABLE_NAME, null, content);
	}

	@Override
	public boolean update(Category model) {
		if (model.isNew())
			throw new IllegalArgumentException(
					"Cannot update a model that is new");
		if (model.isDirty()) {
			Log.v(TAG, String.format("Updating Category for id=%s", model.getID()));
			ContentValues content = getContentValues(model);
			return 1 == database.update(CategoryTable.TABLE_NAME, content,
					CategoryTable.COLUMN_ID + " = " + model.getID(), null);			
		}
		
		return false;
	}
	
	private ContentValues getContentValues(Category model){
		ContentValues content = new ContentValues();
		if(model.getName() == null || model.getName().trim().length() == 0)
			throw new NullPointerException("Can't save Category that has a null name.");
		content.put(CategoryTable.COLUMN_NAME, model.getName());
		if(model.getUser() == null)
			throw new NullPointerException("Can't save Category that has a null User.");
		content.put(CategoryTable.COLUMN_USER_ID, model.getUser().getID());
		return content;
	}

	@Override
	public boolean delete(long id) {
		Log.v(TAG, String.format("Deleting Category for id=%s", id));

		return 1 == database.delete(CategoryTable.TABLE_NAME, CategoryTable.COLUMN_ID + " = " + id, null);
	}

}
